package com.esdk.sql;

import com.esdk.esdk;
import com.esdk.sql.orm.IRow;
import com.esdk.sql.orm.ParentRow;
import com.esdk.utils.CharAppender;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

public class OracleDialect extends SqlDialect{

	public OracleDialect(){
		super(ConnMetaData.DatabaseProductName_Oracle,null,null);
	}
	
  @Override public StringBuilder getSQL(Columns columns,Froms froms,Wheres wheres,String distinct,int offset
			,int limit,OrderBys orderbys,GroupBys groupbys){
  	StringBuilder stmtSql;
		if(limit>0&&offset<=0){
			stmtSql=join("SELECT * FROM (SELECT",distinct,columns.assemble(),froms.assemble()
    			,wheres.assemble(),orderbys.assemble(),groupbys.assemble(),") Where ROWNUM<=",limit);
    }else if(limit>0&&offset>=0) {
    	stmtSql=join("SELECT",distinct,columns.assemble(),"FROM (SELECT ROWNUM ROW_NUM_,tmp.* FROM (SELECT "
    			,columns.assemble(),froms.assemble(),wheres.assemble(),orderbys.assemble(),groupbys.assemble()
    			,")tmp WHERE ROWNUM<=",limit+offset,") WHERE ROW_NUM_>",offset);
    }
    else {
    	return super.getSQL(columns,froms,wheres,distinct,offset,limit,orderbys,groupbys);
    }
		return stmtSql;
	}
  
	@Override public StringBuilder parse(Columns columns,Froms froms,Wheres wheres,String distinct,int offset
				,int limit,OrderBys orderbys,GroupBys groupbys){
		StringBuilder result;
		if(limit>0&&offset<=0){
			result=join("SELECT * FROM (SELECT",distinct,columns.assemble(),froms.assemble()
    			,wheres.getPstmtSql(),orderbys.assemble(),groupbys.assemble(),") Where ROWNUM<=",limit);
    }else if(limit>0&&offset>=0) {
    	CharAppender labels=new CharAppender(',');
    	for(Column item:columns.toArray()) {
    		labels.add(item.getLabel());
    	}
    	result=join("SELECT",labels,"FROM (SELECT ROWNUM ROW_NUM_,tmp.* FROM (SELECT "
    			,distinct,columns.assemble(),froms.assemble(),wheres.getPstmtSql(),orderbys.assemble(),groupbys.assemble()
    			,")tmp WHERE ROWNUM<=",limit+offset,") WHERE ROW_NUM_>",offset);
    }
    else {
    	result=super.parse(columns,froms,wheres,distinct,offset,limit,orderbys,groupbys);
    }
		return result;
	}
	
	@Override
	public StringBuilder parseValues(List<Object[]> values) {
		StringBuilder sb=new StringBuilder();
    for(Iterator<Object[]> iter=values.iterator();iter.hasNext();){
    	Object[] array=iter.next();
    	sb.append("SELECT ");
    	for(int i=0,n=array.length;i<n;i++){
    		sb.append(SQLAssistant.getStmtSqlValue(array[i]));
    		if(i<n-1)
    			sb.append(",");
    	}
    	sb.append(" FROM DUAL");
    	if(iter.hasNext())
    		sb.append(" UNION ");
    }
    return sb;
	}

	/**TODO oracle的批量update拼装，待修复*/
	@Override
	public StringBuilder parseBatchReplace(String tableName,List<IRow> prs,boolean ignoreRowChanged){
		StringBuilder sb=new StringBuilder().append("begin ");
    for(int i=0,n=prs.size();i<n;i++){
    	IRow row=prs.get(i);
    	if(ignoreRowChanged || row.isChanged()) {
				if(row instanceof ParentRow parentRow){
					parentRow.fillCommonFields();
					sb.append(parentRow.showSQL()).append(";");
				}else{
					sb.append("INSERT INTO ");
					sb.append(parseValues(tableName,row.getColumns(),row.toList())).append(";");
				}
    	}
    }
    sb.append(" end;");
    return sb;
	}

	@Override
	public StringBuilder parseBatchInsert(String tableName,String[] fields,List<Object[]> valuesList){
			StringBuilder sb=new StringBuilder().append("begin ");
			for(int i=0,n=valuesList.size();i<n;i++){
				sb.append("INSERT INTO ");
				Object[] values=valuesList.get(i);
				ArrayList<Object[]> list=new ArrayList<>();
				list.add(values);
				sb.append(parseValues(tableName,fields,list)).append(";");
			}
			sb.append(" end;");
			return sb;
	}
}
